/*  This file is part of Basepairs, an application for calculations on
    DNA Sequence polymorphism.
    Copyright (C) 2013 Kim Lindgren

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.*/


package basepairs;

import java.util.ArrayList;

public class Sequences {
    public static int sequenceLength = 0;
    
    public static ArrayList<String> sequences = null;
    public static ArrayList<String> names = new ArrayList<String>();

    public static ArrayList<String> selected = null;
    
    public static ArrayList<Integer> codingRegions = new ArrayList<Integer>();
    
    static ArrayList<Integer> gaps = null;
    
    public static int firstExonOffset = 0;
    
    public static void findGaps(){
        gaps = new ArrayList<Integer>();
        
        if(selected != null){
            for(int x = 0; x < selected.size(); x++){
                String seq = selected.get(x);

                for(int y = 0; y < seq.length(); y++){
                    if(!gaps.contains(y)){
                        String ss = seq.substring(y,y+1);
                        if(ss.equals("-")){
                            gaps.add(y);
                        }
                        else if(ss.equals("~")){
                            gaps.add(y);
                        }
                    }
                }
            }
            
            System.out.println("Ignoring " + gaps.size() + " sites with gaps.");
        }
        else{
            System.out.println("No sequences selected");
        }
    }
    
    public static void selectWholeSequences(){
        selected = sequences;
        sequenceLength = sequences.get(0).length();
        findGaps();
    }
    
    public static void selectCoding(){
        String sequence = "";
        String temp_sequence = "";
        int seq = 0;
        int counter;
        int lower;
        int upper;
        
        selected = new ArrayList<String>();
        
        while(seq < sequences.size()){
            sequence = sequences.get(seq);
            
            counter = 0;
            
            while(counter < codingRegions.size()){
                lower = codingRegions.get(counter);
                upper = codingRegions.get(counter+1);

                temp_sequence = temp_sequence + sequence.substring(lower, upper);

                counter = counter + 2;
            }
            
            selected.add(temp_sequence);
            temp_sequence = "";
            
            seq++;
        }
        
        sequenceLength = selected.get(0).length();
        findGaps();
    }
    
    public static boolean inCodingRegion(int position){
        int seq = 0;
        int counter = 0;
        int lower;
        int upper;
        
        while(counter < codingRegions.size()){
            lower = codingRegions.get(counter);
            upper = codingRegions.get(counter+1);

            if(position >= lower & position <= upper){
                return true;
            }
        }
        
        return false;
    }
    
    public static void selectNonCoding(){
        String sequence = "";
        String temp_sequence = "";
        int seq = 0;
        int counter;
        int lower;
        int upper;
        
        selected = new ArrayList<String>();
        
        while(seq < sequences.size()){
            sequence = sequences.get(seq);
            
            if(codingRegions.get(0) > 1){
                temp_sequence = sequence.substring(0, codingRegions.get(0)-2);
            }
            
            counter = 1;
            
            while(counter < codingRegions.size()-1){
                lower = codingRegions.get(counter);
                upper = codingRegions.get(counter+1)-2;

                temp_sequence = temp_sequence + sequence.substring(lower, upper);

                counter = counter + 2;
            }
            
            temp_sequence = temp_sequence + sequence.substring(codingRegions.get(codingRegions.size()-2));
            
            selected.add(temp_sequence);
            temp_sequence = "";
            
            seq++;
        }
        
        sequenceLength = selected.get(0).length();
        findGaps();
    }
    
    public static ArrayList<String> separateCodons(String sequence, int firstOffset){
        ArrayList<String> codons = new ArrayList<String>();
                
        if(firstOffset > 0){
            codons.add(sequence.substring(0,firstOffset));
        }
        
        while(sequence.length() > firstOffset + 3){
            codons.add(sequence.substring(firstOffset, firstOffset+3));
            firstOffset = firstOffset + 3;
        }
        
        if(sequence.length() > firstOffset){
            codons.add(sequence.substring(firstOffset, sequence.length()));
        }
        
        return codons;
    }
    
    public static ArrayList<Integer> findCodonsWithGaps(int firstOffset){
        ArrayList<Integer> codonGaps = new ArrayList<Integer>();
        
        if(selected != null){
            for(int x = 0; x < selected.size(); x++){
                String seq = selected.get(x);
                
                ArrayList<String> codons = separateCodons(seq, firstOffset);

                for(int y = 0; y < codons.size(); y++){
                    if(!codonGaps.contains(y)){
                        String codon = codons.get(y);
                        if(codon.indexOf("-") >= 0){
                            codonGaps.add(y);
                        }
                        else if(codon.indexOf("~") >= 0){
                            codonGaps.add(y);
                        }
                        else if(codon.length() < 3){
                            codonGaps.add(y);
                        }
                    }
                }
            }
            
            System.out.println("Ignoring " + codonGaps.size() + " codons with gaps.");
        }
        else{
            System.out.println("No sequences selected");
        }
        
        return codonGaps;
    }
    
    public static void defineCodingRegion(int start, int end){
        codingRegions.add(start);
        codingRegions.add(end);
    }
    
    public static boolean positionInCodingRegion(int pos){
        int counter = 0;
        int lower;
        int upper;
        
        while(counter < codingRegions.size()){
            lower = codingRegions.get(counter);
            upper = codingRegions.get(counter+1);
            
            if(pos >= lower){
                if(pos <= upper){
                    return true;
                }
            }
            
            counter = counter + 2;
        }
        
        return false;
    }
}
